package cn.starremote.component.utils.encrypt;

/**
 * @version V1.0
 * @Description: 数据填充接口，提供了 0x00, PKCS#5(PKCS#7)数据填充方式
 * @auther:wangjw
 */
public final class DataPadding {
	private DataPadding() {}
	
	/**
	 * 不填充
	 * @param 	data
	 * 			需要填充的数据
	 * @return 	填充后的数据
	 */
	public static byte[] encodeWithNoPadding(byte[] data) {
		return data;
	}
	
	/**
	 * 不填充
	 * @param 	data
	 * 			解填充的数据
	 * @return 	解填充后的数据
	 */
	public static byte[] decodeWithNoPadding(byte[] data) {
		return data;
	}
	
	/**
	 * [数据 + n bytes 0x00] 的方式填充数据到 blockSize 的倍数
	 * @param 	data
	 * 			待填充的数据
	 * @param 	blockSize
	 * 			数据块的大小
	 * @return 	填充后的数据
	 */
	public static byte[] encodeWith0x00(byte[] data, int blockSize) {
		final int len = data.length + blockSize - data.length % blockSize;
		final byte[] buffer = new byte[len];
		System.arraycopy(data, 0, buffer, 0, data.length);
		for (int i = buffer.length - 1; i >= data.length; i--) {
			buffer[i] = 0x00;
		}
		return buffer;
	}
	
	/**
	 * 解析 [数据 + n bytes 0x00] 方式的填充数据
	 * @param 	data
	 * 		 	解填充的数据
	 * @return 	解析后的数据
	 */
	public static byte[] decodeWith0x00(byte[] data) {
		int counts = 0;
		for (int i = data.length - 1; i >= 0; i--) {
			if (data[i] == 0) {
				counts += 1;
			} else {
				break;
			}
		}
		final int len = data.length - counts;
		final byte[] buffer = new byte[len];
		System.arraycopy(data, 0, buffer, 0, len);
		return buffer;
	}
	
	/**
	 * [数据 + 0x80 + n bytes 0x00] 的方式填充数据到 blockSize 的倍数
	 * @param 	data
	 * 			待填充的数据
	 * @param 	blockSize
	 * 			数据块的大小
	 * @return 	填充后的数据
	 */
	public static byte[] encodeWith0x80(byte[] data, int blockSize) {
		final int len = data.length + blockSize - data.length % blockSize;
		final byte[] buffer = new byte[len];
		System.arraycopy(data, 0, buffer, 0, data.length);
		buffer[data.length] = (byte) 0x80;
		for (int i = data.length + 1; i < len; i++) {
			buffer[i] = 0x00;
		}
		return buffer;
	}
	
	/**
	 * 解析 [数据 + 0x80 + n bytes 0x00] 方式的填充数据
	 * @param 	data
	 * 		 	解填充的数据
	 * @return 	解析后的数据
	 */
	public static byte[] decodeWith0x80(byte[] data) {
		int counts = 1;
		for (int i = data.length -1; i >= 0; i--) {
			if (data[i] == 0 || data[i] == 0x80) {
				counts += 1;
			} else {
				break;
			}
		}
		final int len = data.length - counts;
		final byte[] buffer = new byte[len];
		System.arraycopy(data, 0, buffer, 0, len);
		return buffer;
	}
	
	/**
	 * PKCS#5(PKCS#7) 的方式填充数据到 blockSize 的倍数
	 * @param 	data
	 * 			待填充的数据
	 * @param 	blockSize
	 * 			数据块的大小
	 * @return 	填充后的数据
	 */
	public static byte[] encodeWithPKCS5(byte[] data, int blockSize) {
		final int plen = blockSize - data.length % blockSize;
		final int len = data.length + plen;
		final byte[] buffer = new byte[len];
		System.arraycopy(data, 0, buffer, 0, data.length);
		for (int i = data.length; i < len; i++) {
			buffer[i] = (byte) ((byte) plen & 0xFF);
		}
		return buffer;
	}
	
	/**
	 * 解析 PKCS#5(PKCS#7) 方式的填充数据
	 * @param 	data
	 * 		 	解填充的数据
	 * @return 	解析后的数据
	 */
	public static byte[] decodeWithPKCS5(byte[] data) {
		final int len = data[data.length - 1];
		final byte[] buffer = new byte[data.length - len];
		System.arraycopy(data, 0, buffer, 0, data.length - len);
		return buffer;
	}
}
